import {
  checkTokenExpired,
  sendMessage,
  removeUrlSearchParams,
  getFileTypeFromUrl,
  formatTime,
  sleep,
} from "@/utils/tools";
import ConcurrentExecutor from "@/class/ConcurrentExecutor";
import type {
  CollectConfig,
  TCollectCountMap,
  TMultiKeywordCollectData,
  TAsinUrlMap,
} from "@/type/collect";
import {
  MAX_SPU_COLLECT_SKU_COUNT,
  MAX_DEAL_IMAGE_COUNT,
} from "@/constants/collect";
import amazonConfig from "@/platform/amazon/index";
import type { TParseSpuHtml, TParseSkuHtml } from "./platform/type";
import { FILE_CONTENT_TYPE } from "@/constants/file";
import { getImageFile } from "@/utils/file";

let parseSpuHtml: TParseSpuHtml = ({ html, url, collectConfig }) => {
  return {};
};
let parseSkuHtml: TParseSkuHtml = ({ html, url, collectConfig }) => {
  return {};
};

function setConfigByUrl(url: string) {
  if (url.includes("amazon")) {
    ({ parseSpuHtml, parseSkuHtml } = amazonConfig);
  }
}

const extractAsin = (url: string) => {
  if (url.includes("/dp/")) {
    return url.match(/\/dp\/([A-Z0-9]{10})/i)?.[1]?.toUpperCase() || null;
  } else if (url.includes("/gp/")) {
    return (
      url.match(/\/gp\/aw\/d\/([A-Z0-9]{10})/i)?.[1]?.toUpperCase() || null
    );
  }
  return "";
};

let abortController = new AbortController();

const containerId = "baoyiCollectContainer";
const buttonId = "baoyiCollectButton";
const cancelButtonId = "baoyiCollectCancelButton";
const statusPanelId = "baoyiCollectStatusPanel";
const buttonTextId = "baoyiCollectButtonText";
const buttonTextFaildDivId = "baoyiCollectButtonTextFailedDiv";
const statusCurrentGoodsId = "baoyiCollectStatusCurrentGoods";
const statusTotalGoodsId = "baoyiCollectStatusTotalGoods";
const statusFailedGoodsId = "baoyiCollectStatusFailedGoods";
const statusSkippedGoodsId = "baoyiCollectStatusSkippedGoods";

function createButton() {
  // Check if container already exists to avoid duplicates
  if (document.getElementById(containerId)) return;

  // 创建主容器
  const container = document.createElement("div");
  container.id = containerId;
  container.style.position = "fixed";
  container.style.bottom = "20px";
  container.style.left = "50%";
  container.style.transform = "translateX(-50%)";
  container.style.zIndex = "1000000";
  container.style.display = "flex";
  container.style.flexDirection = "column";
  container.style.gap = "10px";
  container.style.fontFamily = "Arial, sans-serif";
  document.body.appendChild(container);

  // 创建采集按钮
  const button = document.createElement("button");
  button.id = buttonId;
  button.style.backgroundColor = "#0064fa";
  button.style.color = "#FFF";
  button.style.border = "none";
  button.style.borderRadius = "8px";
  button.style.padding = "12px 20px";
  button.style.cursor = "pointer";
  button.style.fontSize = "14px";
  button.style.fontWeight = "500";
  button.style.boxShadow = "0 2px 8px rgba(0, 100, 250, 0.3)";
  button.style.transition = "all 0.3s ease";
  button.style.minWidth = "160px";

  const buttonText = document.createElement("span");
  buttonText.textContent = "此页面支持自动化采集发布到爆蚁ERP【开始】";
  buttonText.id = buttonTextId;
  button.appendChild(buttonText);

  button.addEventListener("click", () => {
    startCollect();
  });

  // 添加悬停效果
  button.addEventListener("mouseenter", () => {
    button.style.backgroundColor = "#0052cc";
    button.style.transform = "translateY(-1px)";
    button.style.boxShadow = "0 4px 12px rgba(0, 100, 250, 0.4)";
  });

  button.addEventListener("mouseleave", () => {
    button.style.backgroundColor = "#0064fa";
    button.style.transform = "translateY(0)";
    button.style.boxShadow = "0 2px 8px rgba(0, 100, 250, 0.3)";
  });

  container.appendChild(button);

  // 创建取消按钮
  const cancelButton = document.createElement("button");
  cancelButton.id = cancelButtonId;
  cancelButton.style.backgroundColor = "#f44336";
  cancelButton.style.color = "#FFF";
  cancelButton.style.border = "none";
  cancelButton.style.borderRadius = "8px";
  cancelButton.style.padding = "12px 20px";
  cancelButton.style.cursor = "pointer";
  cancelButton.style.fontSize = "14px";
  cancelButton.style.fontWeight = "500";
  cancelButton.style.boxShadow = "0 2px 8px rgba(244, 67, 54, 0.3)";
  cancelButton.style.transition = "all 0.3s ease";
  cancelButton.style.minWidth = "160px";
  cancelButton.style.display = "none"; // 初始隐藏
  cancelButton.textContent = "取消采集";

  cancelButton.addEventListener("click", (e) => {
    e.stopPropagation();
    e.preventDefault();
    // 阻止其他点击事件
    if (e.cancelable) {
      e.stopImmediatePropagation();
    }
    doCancelCollectChangeButtonHtmlToBackground();
  });

  // 添加悬停效果
  cancelButton.addEventListener("mouseenter", () => {
    cancelButton.style.backgroundColor = "#d32f2f";
    cancelButton.style.transform = "translateY(-1px)";
    cancelButton.style.boxShadow = "0 4px 12px rgba(244, 67, 54, 0.4)";
  });

  cancelButton.addEventListener("mouseleave", () => {
    cancelButton.style.backgroundColor = "#f44336";
    cancelButton.style.transform = "translateY(0)";
    cancelButton.style.boxShadow = "0 2px 8px rgba(244, 67, 54, 0.3)";
  });

  container.appendChild(cancelButton);

  // 创建状态显示面板
  const statusPanel = document.createElement("div");
  statusPanel.id = statusPanelId;
  statusPanel.style.backgroundColor = "rgba(255, 255, 255, 0.95)";
  statusPanel.style.border = "1px solid #e0e0e0";
  statusPanel.style.borderRadius = "8px";
  statusPanel.style.padding = "12px";
  statusPanel.style.boxShadow = "0 2px 12px rgba(0, 0, 0, 0.1)";
  statusPanel.style.minWidth = "200px";
  statusPanel.style.display = "none"; // 初始隐藏
  statusPanel.style.fontSize = "12px";
  statusPanel.style.color = "#333";

  const currentGoodsDiv = document.createElement("div");
  currentGoodsDiv.style.marginBottom = "6px";
  currentGoodsDiv.style.display = "flex";
  currentGoodsDiv.style.justifyContent = "space-between";
  currentGoodsDiv.innerHTML =
    '<span style="color: #666;">已采集发布:</span><span id="' +
    statusCurrentGoodsId +
    '" style="font-weight: 500; color: #0064fa;">0</span>';
  statusPanel.appendChild(currentGoodsDiv);

  const skippedGoodsDiv = document.createElement("div");
  skippedGoodsDiv.style.display = "flex";
  skippedGoodsDiv.style.justifyContent = "space-between";
  skippedGoodsDiv.style.marginTop = "6px";
  skippedGoodsDiv.style.cursor = "pointer";
  skippedGoodsDiv.style.textDecoration = "underline";
  skippedGoodsDiv.innerHTML =
    '<span style="color: #666;">采集跳过:</span><span id="' +
    statusSkippedGoodsId +
    '" style="font-weight: 500; color: #ff9800;">0</span>';
  statusPanel.appendChild(skippedGoodsDiv);
  // 添加点击事件，显示失败商品列表
  skippedGoodsDiv.addEventListener("click", handleShowFailedGoodsList);

  const failedGoodsDiv = document.createElement("div");
  failedGoodsDiv.style.display = "flex";
  failedGoodsDiv.style.justifyContent = "space-between";
  failedGoodsDiv.style.marginTop = "6px";
  failedGoodsDiv.style.cursor = "pointer";
  failedGoodsDiv.style.textDecoration = "underline";
  failedGoodsDiv.innerHTML =
    '<span style="color: #666;">采集失败:</span><span id="' +
    statusFailedGoodsId +
    '" style="font-weight: 500; color: #f44336;">0</span>';

  // 添加点击事件，显示失败商品列表
  failedGoodsDiv.addEventListener("click", handleShowFailedGoodsList);

  statusPanel.appendChild(failedGoodsDiv);

  const totalGoodsDiv = document.createElement("div");
  totalGoodsDiv.style.display = "flex";
  totalGoodsDiv.style.justifyContent = "space-between";
  totalGoodsDiv.innerHTML =
    '<span style="color: #666;">总商品:</span><span id="' +
    statusTotalGoodsId +
    '" style="font-weight: 500;">-</span>';
  statusPanel.appendChild(totalGoodsDiv);

  container.appendChild(statusPanel);
}

// 1. 配置目标元素和子元素信息
// 2. 创建要插入的子元素（根据你提供的结构生成）
function createClickGuard(delay = 800) {
  let lastTriggered = 0;
  return () => {
    const now = Date.now();
    if (now - lastTriggered < delay) {
      return false;
    }
    lastTriggered = now;
    return true;
  };
}

function createInjectElement(
  option = {
    offsetRight: 0,
  }
) {
  const { offsetRight = 0 } = option;
  // 最外层容器
  const outerDiv = document.createElement("div");
  outerDiv.dataset.baoyiCollectBtn = "v1";
  outerDiv.style.cssText = `position: absolute; top: 10px; right: ${
    10 + offsetRight
  }px; z-index: 10000; pointer-events: all;`;

  // 按钮容器
  const btnDiv = document.createElement("div");
  btnDiv.style.cssText =
    "cursor: pointer; width: 28px; height: 28px; border-radius: 8px; background: rgb(0,100,250); padding: 4px; pointer-events: auto; user-select: none; display: flex; align-items: center; justify-content: center; transition: background-color 0.2s;";

  // 按钮文本
  const textSpan = document.createElement("span");
  textSpan.style.cssText =
    "color: rgb(255, 255, 255); font-weight: bold; font-size: 11px;";
  textSpan.textContent = "采";

  // 组装结构
  btnDiv.appendChild(textSpan);
  outerDiv.appendChild(btnDiv);

  return outerDiv;
}

function initCollect() {
  createButton();
  sendMessage({
    action: "contentInitCollect",
  });
  // chrome.runtime.sendMessage({ action: "getTabId" }, (response) => {
  //   console.log("当前 tabId:", response.tabId);
  // });
}

if (
  document.readyState === "interactive" ||
  document.readyState === "complete"
) {
  // 如果已就绪，直接执行
  initCollect();
} else {
  // 如果未就绪，监听事件触发
  document.addEventListener("DOMContentLoaded", initCollect);
}

const plugsBaoyiCollectIndicatorId = "plugs-baoyi-collect-indicator";
function initPage() {
  initCollect();
  setConfigByUrl(location.href);

  // 创建隐藏指示器（避免重复创建）
  if (!document.getElementById(plugsBaoyiCollectIndicatorId)) {
    const indicator = document.createElement("div");
    indicator.id = plugsBaoyiCollectIndicatorId;
    indicator.style.display = "none";
    document.body.appendChild(indicator);
  }

  if (location.href.includes("/dp/") || location.href.includes("/gp/")) {
    const mainImageContainer = document.getElementById("main-image-container");
    if (!mainImageContainer) return;
    const existsInjectElement = mainImageContainer.querySelector(
      "[data-baoyi-collect-btn='v1']"
    );
    if (!existsInjectElement) {
      const injectElement = createInjectElement({ offsetRight: 40 });

      const detailPageClickGuard = createClickGuard(1000);
      injectElement.addEventListener("click", async function (e) {
        e.stopPropagation();
        e.preventDefault();
        if (!detailPageClickGuard()) {
          return;
        }
        startCollect();
      });

      mainImageContainer.appendChild(injectElement);
    }
  } else {
    // 商品卡片
    const listItems = Array.from(
      document.querySelectorAll("[data-asin]")
    ).filter((el) => el.getAttribute("data-asin"));

    const listCollectClickGuard = createClickGuard(1000);
    listItems.forEach((item) => {
      const asin = item.getAttribute("data-asin");
      const itemDetailElement: HTMLAnchorElement | null = item.querySelector(
        ".s-product-image-container a"
      );
      if (!itemDetailElement) return;

      const detailUrl = itemDetailElement.href || "";
      const existsInjectElement = itemDetailElement.querySelector(
        "[data-baoyi-collect-btn='v1']"
      );

      if (asin && detailUrl && !existsInjectElement) {
        const injectElement = createInjectElement();

        injectElement.addEventListener("click", async function (e) {
          e.stopPropagation();
          e.preventDefault();
          if (!listCollectClickGuard()) {
            return;
          }

          const storage = await chrome.storage.sync.get([
            "baoyiplus_collectConfig",
          ]);

          if (storage.baoyiplus_collectConfig) {
            const { baoyiplus_collectConfig } = storage;
            const { claimTemplate } = baoyiplus_collectConfig;

            startCollectChangeButtonHtml();
            collectCurrentPage(
              {
                [asin]: { url: detailUrl, claimTemplate },
              },
              {
                ...baoyiplus_collectConfig,
                isManualCollect: false,
              }
            );

            injectElement.textContent = "已采";
            injectElement.style.pointerEvents = "none";
            injectElement.style.opacity = "0.6";
          }
        });

        itemDetailElement.appendChild(injectElement);
      }
    });
  }
}

let pageDebounceTimer: any = null;

const observer = new MutationObserver(() => {
  clearTimeout(pageDebounceTimer);
  pageDebounceTimer = setTimeout(() => {
    initPage(); // 页面任何 DOM 更新，都可补齐注入
  }, 300);
});

observer.observe(document.documentElement, { childList: true, subtree: true });

function onUrlChange(callback: any) {
  let oldHref = location.href;
  const pushState = history.pushState;
  history.pushState = function (...args) {
    pushState.apply(this, args);
    if (oldHref !== location.href) {
      oldHref = location.href;
      callback();
    }
  };

  // hook replaceState
  const replaceState = history.replaceState;
  history.replaceState = function (...args) {
    replaceState.apply(this, args);
    if (oldHref !== location.href) {
      oldHref = location.href;
      callback();
    }
  };

  // 前进/后退
  window.addEventListener("popstate", () => {
    if (oldHref !== location.href) {
      oldHref = location.href;
      callback();
    }
  });

  // fallback：每秒检查一次 URL
  setInterval(() => {
    if (oldHref !== location.href) {
      oldHref = location.href;
      callback();
    }
  }, 1000);
}

// 翻页后执行一次 initPage（剩下的由 MutationObserver 自动补充）
onUrlChange(() => {
  initPage();
});

let startColletTime: any = null;
let isCollecting = false;
function initCollectPanel() {
  if (!isCollecting) {
    isCollecting = true;
    // 更新按钮文本
    const buttonTextElement = document.getElementById(buttonTextId);
    if (buttonTextElement) {
      buttonTextElement.textContent = "采集发布中...(可继续采集)";
    }

    const buttonTextFaildDiv = document.getElementById(buttonTextFaildDivId);
    if (buttonTextFaildDiv) {
      buttonTextFaildDiv.remove();
    }

    // 显示取消按钮
    const cancelButton = document.getElementById(cancelButtonId);
    if (cancelButton) {
      cancelButton.style.display = "block";
    }

    // 显示状态面板
    const statusPanel = document.getElementById(statusPanelId);
    if (statusPanel) {
      statusPanel.style.display = "block";
    }
  }
}
function startCollectChangeButtonHtml() {
  // 启动超时机制
  // startCollectTimeout();
  startColletTime = performance.now();

  initCollectPanel();

  // 确保状态显示元素存在
  const statusCurrentGoodsElement =
    document.getElementById(statusCurrentGoodsId);
  if (statusCurrentGoodsElement && !statusCurrentGoodsElement.textContent) {
    statusCurrentGoodsElement.textContent = "0";
  }

  const statusTotalGoodsElement = document.getElementById(statusTotalGoodsId);
  if (statusTotalGoodsElement && statusTotalGoodsElement.textContent === "-") {
    statusTotalGoodsElement.textContent = "0";
  }

  const statusFailedGoodsElement = document.getElementById(statusFailedGoodsId);
  if (
    statusFailedGoodsElement &&
    statusFailedGoodsElement.textContent !== "0"
  ) {
    statusFailedGoodsElement.textContent = "0";
  }

  const statusSkippedGoodsElement =
    document.getElementById(statusSkippedGoodsId);
  if (
    statusSkippedGoodsElement &&
    statusSkippedGoodsElement.textContent !== "0"
  ) {
    statusSkippedGoodsElement.textContent = "0";
  }
}

function doCancelCollectChangeButtonHtmlToBackground() {
  sendMessage({
    action: "doCancelCollectChangeButtonHtmlToBackground",
  });
  if (!abortController.signal.aborted) {
    abortController.abort();
    abortController = new AbortController();
  }
}
function cancelCollectChangeButtonHtml() {
  // 更新按钮文本为取消状态
  const buttonTextElement = document.getElementById(buttonTextId);
  if (buttonTextElement) {
    buttonTextElement.textContent = "此页面支持自动化采集发布到爆蚁ERP【开始】";
  }

  // 恢复主按钮状态
  const button = document.getElementById(buttonId);
  if (button) {
    (button as HTMLButtonElement).disabled = false;
    (button as HTMLButtonElement).style.opacity = "1";
    (button as HTMLButtonElement).style.cursor = "pointer";
  }

  // 隐藏取消按钮
  const cancelButton = document.getElementById(cancelButtonId);
  if (cancelButton) {
    cancelButton.style.display = "none";
  }

  // 隐藏状态面板
  const statusPanel = document.getElementById(statusPanelId);
  if (statusPanel) {
    statusPanel.style.display = "none";
  }
  isCollecting = false;

  // 更新显示
  const statusCurrentGoodsElement =
    document.getElementById(statusCurrentGoodsId);
  if (statusCurrentGoodsElement) {
    statusCurrentGoodsElement.textContent = "0";
  }

  const statusTotalGoodsElement = document.getElementById(statusTotalGoodsId);
  if (statusTotalGoodsElement) {
    statusTotalGoodsElement.textContent = "0";
  }

  const statusFailedGoodsElement = document.getElementById(statusFailedGoodsId);
  if (statusFailedGoodsElement) {
    statusFailedGoodsElement.textContent = "0";
  }

  const statusSkippedGoodsElement =
    document.getElementById(statusSkippedGoodsId);
  if (statusSkippedGoodsElement) {
    statusSkippedGoodsElement.textContent = "0";
  }
}

function doEndCollectChangeButtonHtmlToBackground() {
  sendMessage({
    action: "doEndCollectChangeButtonHtmlToBackground",
  });
}
function endCollectChangeButtonHtml(collectCountMap: TCollectCountMap) {
  // 清理超时定时器
  // clearCollectTimeout();
  // const endCollectTIme = performance.now();
  // console.log(
  //   "采集时间",
  //   ((endCollectTIme - startColletTime) / 1000).toFixed(2)
  // );
  // 更新按钮文本
  const buttonTextElement = document.getElementById(buttonTextId);
  if (buttonTextElement) {
    const button = document.getElementById(buttonId);
    if (button) {
      const { skipped, failed } = collectCountMap;
      const unCollectCount = Number(skipped || 0) + Number(failed || 0);
      buttonTextElement.textContent = `自动化采集发布完成,共采集发布${collectCountMap.current}个商品,发布结果请到爆蚁ERP中查看`;

      if (unCollectCount) {
        const existingFailedDiv = document.getElementById(
          "baoyiCollectFailedDiv"
        );
        if (existingFailedDiv) {
          existingFailedDiv.remove();
        }

        const failedDiv = document.createElement("div");
        failedDiv.id = buttonTextFaildDivId;
        failedDiv.style.display = "inline";
        failedDiv.style.cursor = "pointer";
        failedDiv.style.color = "#f44336";
        failedDiv.style.textDecoration = "underline";
        failedDiv.style.marginLeft = "4px";
        failedDiv.textContent = `,采集失败或跳过${unCollectCount}个`;

        // 添加点击事件，显示失败商品列表
        failedDiv.addEventListener("click", handleShowFailedGoodsList);

        // 将失败div添加到button中
        button.appendChild(failedDiv);
      }
    }
  }
  isCollecting = false;

  // 恢复主按钮状态
  const button = document.getElementById(buttonId);
  if (button) {
    (button as HTMLButtonElement).disabled = false;
    (button as HTMLButtonElement).style.opacity = "1";
    (button as HTMLButtonElement).style.cursor = "pointer";
  }

  // 隐藏取消按钮
  const cancelButton = document.getElementById(cancelButtonId);
  if (cancelButton) {
    cancelButton.style.display = "none";
  }

  // 更新显示
  const statusCurrentGoodsElement =
    document.getElementById(statusCurrentGoodsId);
  if (statusCurrentGoodsElement) {
    statusCurrentGoodsElement.textContent = "0";
  }

  const statusTotalGoodsElement = document.getElementById(statusTotalGoodsId);
  if (statusTotalGoodsElement) {
    statusTotalGoodsElement.textContent = "0";
  }

  const statusFailedGoodsElement = document.getElementById(statusFailedGoodsId);
  if (statusFailedGoodsElement) {
    statusFailedGoodsElement.textContent = "0";
  }

  const statusSkippedGoodsElement =
    document.getElementById(statusSkippedGoodsId);
  if (statusSkippedGoodsElement) {
    statusSkippedGoodsElement.textContent = "0";
  }

  // 隐藏状态面板
  const statusPanel = document.getElementById(statusPanelId);
  if (statusPanel) {
    statusPanel.style.display = "none";
  }
}

function doAddCollectCountCurrentToBackground(changeValue: number) {
  sendMessage({
    action: "doAddCollectCountCurrentToBackground",
    data: {
      changeValue,
    },
  });
}
function doAddCollectCountFailedToBackground(changeValue: number) {
  sendMessage({
    action: "doAddCollectCountFailedToBackground",
    data: {
      changeValue,
    },
  });
}
function doAddCollectCountSkippedToBackground(changeValue: number) {
  sendMessage({
    action: "doAddCollectCountSkippedToBackground",
    data: {
      changeValue,
    },
  });
}

function changeCollectCount(collectCountMap: TCollectCountMap) {
  initCollectPanel();

  // 成功条数
  const statusCurrentGoodsElement =
    document.getElementById(statusCurrentGoodsId);
  if (statusCurrentGoodsElement) {
    statusCurrentGoodsElement.textContent = collectCountMap.current.toString();
  }

  // 失败条数
  const statusFailedGoodsElement = document.getElementById(statusFailedGoodsId);
  if (statusFailedGoodsElement) {
    statusFailedGoodsElement.textContent = collectCountMap.failed.toString();
  }

  // 跳过条数
  const statusSkippedGoodsElement =
    document.getElementById(statusSkippedGoodsId);
  if (statusSkippedGoodsElement) {
    statusSkippedGoodsElement.textContent = collectCountMap.skipped.toString();
  }

  // 总条数
  const statusTotalGoodsElement = document.getElementById(statusTotalGoodsId);
  if (statusTotalGoodsElement) {
    statusTotalGoodsElement.textContent = collectCountMap.total.toString();
  }
}

function getInputValues(): Promise<{
  page: number;
} | null> {
  // 创建对话框容器
  const dialog = document.createElement("div");
  dialog.style.position = "fixed";
  dialog.style.top = "50%";
  dialog.style.left = "50%";
  dialog.style.transform = "translate(-50%, -50%)";
  dialog.style.backgroundColor = "white";
  dialog.style.padding = "20px";
  dialog.style.borderRadius = "8px";
  dialog.style.boxShadow = "0 0 10px rgba(0,0,0,0.2)";
  dialog.style.zIndex = "9999";

  dialog.innerHTML = `
    <h3 style="margin-top: 0;">采集发布页数</h3>
    <div style="margin-bottom: 15px;">
      采集发布页数
      <input type="number" id="maxPagesInput" step="1" min="1" value="5" 
             style="width: 100%; padding: 8px; box-sizing: border-box; border: 1px solid #ccc; border-radius: 4px;">
    </div>
    <div style="display: flex; justify-content: space-between;">
      <button id="cancelBtn" style="padding: 8px 16px; background-color: #f44336; color: white; border: none; border-radius: 4px; cursor: pointer;">取消</button>
      <button id="confirmBtn" style="padding: 8px 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">确认</button>
    </div>
  `;

  // 添加到body
  document.body.appendChild(dialog);

  const maxPagesInput = document.getElementById(
    "maxPagesInput"
  ) as HTMLInputElement;

  // 返回Promise
  return new Promise((resolve, reject) => {
    // 确认按钮点击事件
    document.getElementById("confirmBtn")?.addEventListener("click", () => {
      const page = parseInt(maxPagesInput.value);

      // 验证输入
      if (isNaN(page)) {
        alert("请输入有效的页数！");
        reject();
        return;
      }

      if (page <= 0) {
        alert("页数必须大于0！");
        reject();
        return;
      }

      // 移除对话框
      document.body.removeChild(dialog);

      // 返回结果
      resolve({ page });
    });

    // 取消按钮点击事件
    document.getElementById("cancelBtn")?.addEventListener("click", () => {
      document.body.removeChild(dialog);
      resolve(null);
    });
  });
}
/**
 * 处理显示失败商品列表的点击事件
 * @param e 点击事件对象
 */
function handleShowFailedGoodsList(e: Event) {
  e.stopPropagation(); // 阻止事件冒泡，避免触发父级容器button的点击事件
  e.preventDefault();

  (async () => {
    try {
      // 从 background 获取 collectResultList
      const response = await sendMessage<{ data: any[] }>({
        action: "getCollectResultList",
      });

      const resultList = response?.data || [];

      // 显示对话框
      showCollectResultListDialog(resultList);
    } catch (error) {
      console.error("获取采集结果列表失败:", error);
      alert("获取采集结果列表失败");
    }
  })();
}

// #region [采集结果对话框]
const collectResultListDialogId = "baoyi_collectResultListDialogId";
function showCollectResultListDialog(resultList: any[]) {
  if (document.getElementById(collectResultListDialogId)) {
    return;
  }

  // 过滤出失败的结果
  const failResults = resultList.filter((item) =>
    ["fail", "skip"].includes(item.status)
  );

  // 创建对话框容器
  const dialog = document.createElement("div");
  dialog.id = collectResultListDialogId;
  dialog.style.position = "fixed";
  dialog.style.top = "5%";
  dialog.style.left = "50%";
  dialog.style.transform = "translate(-50%, 0)";
  dialog.style.backgroundColor = "white";
  dialog.style.padding = "20px";
  dialog.style.borderRadius = "8px";
  dialog.style.boxShadow = "0 0 10px rgba(0,0,0,0.2)";
  dialog.style.zIndex = "10000";
  dialog.style.maxWidth = "1000px";
  dialog.style.maxHeight = "80vh";
  dialog.style.overflow = "auto";

  let content = "";

  if (!failResults || failResults.length === 0) {
    content = `<p style='color: #666;'>暂无失败的采集结果</p>`;
  } else {
    content = `
      <h3 style="margin-top: 0; margin-bottom: 15px;">
        采集跳过或失败列表 (共 ${failResults.length} 条)
      </h3>
      <div style="background: #FFF6E0; color: #E67C12; font-size: 14px; margin-bottom: 15px; padding: 10px 16px; border-radius: 5px; border-left: 4px solid #FFE0A0;">
        <b>提示：</b>重新采集的商品，将以最新的采集配置进行采集
      </div>

      <button id="retrySkipBtn"
        style="margin-bottom: 15px; padding: 4px 8px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">
        重试跳过的商品
      </button>
      <button id="retryFailBtn"
        style="margin-bottom: 15px; padding: 4px 8px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">
        重试失败的商品
      </button>
      <button id="retryAllBtn"
        style="margin-bottom: 15px; padding: 4px 8px; background-color: #2196F3; color: white; border: none; border-radius: 4px; cursor: pointer;">
        全部重试
      </button>

      <div style="max-height: 45vh; overflow-y: auto;">
        <table style="width: 100%; border-collapse: collapse; font-size: 14px;">
          <thead>
            <tr>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">ASIN</th>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">URL</th>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">状态</th>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">原因</th>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">时间</th>
              <th style="border-bottom: 2px solid #ddd; padding: 8px; text-align: left;">操作</th>
            </tr>
          </thead>
          <tbody>
            ${failResults
              .map((item, index) => {
                const isFail = item.status === "fail";
                const backgroundColor = isFail ? "#fef0f0" : "#fdf6ec";
                const textColor = isFail ? "#f56c6c" : "#e6a23c";
                const borderColor = isFail ? "#fde2e2" : "#faecd8";
                const statusText = isFail ? "失败" : "跳过";
                return `
                  <tr style="border-bottom: 1px solid #f0f0f0;">
                    <td style="padding: 8px; word-break: break-all;">${
                      item.asin || "-"
                    }</td>
                    <td style="
                      padding: 8px; 
                      max-width: 200px;
                      width: 200px;
                      white-space: nowrap;
                      overflow: hidden;
                      text-overflow: ellipsis;
                    ">
                      ${
                        item.url
                          ? `<a href="${item.url}" target="_blank" style="color: #2196F3; text-decoration: none;">${item.url}</a>`
                          : "-"
                      }
                    </td>
                    <td style="padding: 8px;">
                      <span style="
                        display: inline-flex;
                        align-items: center;
                        justify-content: center;
                        padding: 2px 8px;
                        background-color: ${backgroundColor};
                        color: ${textColor};
                        border: 1px solid ${borderColor};
                        border-radius: 4px;
                        font-size: 12px;
                        line-height: 1;
                        white-space: nowrap;
                        font-weight: 500;
                      ">${statusText}</span>
                    </td>
                    <td style="padding: 8px; color: #f44336; word-break: break-all;">${
                      item.reason || "-"
                    }</td>
                    <td style="padding: 8px; color: #666; word-break: break-all;width: 100px">${
                      item.time || "-"
                    }</td>
                    <td style="padding: 8px;width: 70px">
                      <button class="retrySingleBtn" data-index="${index}"
                        style="padding: 6px 12px; background-color: #ff9800; color: white; border: none; border-radius: 4px; cursor: pointer;">
                        重试
                      </button>
                    </td>
                  </tr>
                `;
              })
              .join("")}
          </tbody>
        </table>
      </div>
    `;
  }

  dialog.innerHTML = `
    ${content}
    <div style="display: flex; justify-content: flex-end; margin-top: 15px;">
      <button id="closeResultDialogBtn"
        style="padding: 8px 16px; background-color: #4CAF50; color: white; border: none; border-radius: 4px; cursor: pointer;">
        关闭
      </button>
    </div>
  `;

  document.body.appendChild(dialog);

  // 关闭按钮
  document
    .getElementById("closeResultDialogBtn")
    ?.addEventListener("click", () => {
      document.body.removeChild(dialog);
    });

  // 点击背景关闭
  dialog.addEventListener("click", (e) => {
    if (e.target === dialog) document.body.removeChild(dialog);
  });

  // 重试跳过
  document.getElementById("retrySkipBtn")?.addEventListener("click", () => {
    const list = failResults.filter((item) => item.status === "skip");
    handleRetryAll(list);
    document.body.removeChild(dialog);
  });
  // 重试失败
  document.getElementById("retryFailBtn")?.addEventListener("click", () => {
    const list = failResults.filter((item) => item.status === "fail");
    handleRetryAll(list);
    document.body.removeChild(dialog);
  });
  // 全部重试
  document.getElementById("retryAllBtn")?.addEventListener("click", () => {
    handleRetryAll(failResults);
    document.body.removeChild(dialog);
  });

  // 单个重试
  dialog.querySelectorAll(".retrySingleBtn").forEach((btn) => {
    btn.addEventListener("click", (e) => {
      const index = (e.target as HTMLElement).dataset.index;
      if (index !== undefined) {
        const item = failResults[parseInt(index)];
        handleRetrySingle(item);

        // 删除当前行
        const row = (e.target as HTMLElement).closest("tr");
        row?.remove();
        if (failResults.length === 1) {
          document.body.removeChild(dialog);
        }
      }
    });
  });
}

// 全部重试处理函数（需要根据实际业务逻辑实现）
function handleRetryAll(failResults: any[]) {
  sendMessage({
    action: "retryCollectGoods",
    data: failResults,
  });
}

// 单个重试处理函数（需要根据实际业务逻辑实现）
function handleRetrySingle(item: any) {
  sendMessage({
    action: "retryCollectGoods",
    data: [item],
  });
  // 这里添加实际的重试逻辑
}
// #endregion

// #region [获取SKU]
function parseDimensionValuesDisplayData(html: string) {
  try {
    const m = html.match(/"dimensionValuesDisplayData"\s*:\s*({[^}]+})/);
    return m ? Object.keys(JSON.parse(m[1])) : [];
  } catch {
    return [];
  }
}
// #endregion

// #region [parentAsin]
function extractParentAsin(html: string): string | null {
  // 正则表达式匹配parentAsin字段及其值
  // 匹配 "parentAsin" : "XXX" 格式，其中XXX为要提取的值
  const regex = /"parentAsin"\s*:\s*"([^"]+)"/;
  const match = html.match(regex);

  // 如果匹配到结果，返回捕获组中的值，否则返回null
  return match ? match[1] : null;
}
// #endregion

// 请求计数器，用于跟踪正在进行的请求数量
let requestCounters = {
  content: 0,
  background: 0,
};

/**
 * 根据当前正在进行的请求数量比例来决定请求位置
 * content 占 2/5，background 占 3/5
 * @returns "content" | "background"
 */
function getRequestLocation(): "content" | "background" {
  return "content";
  const total = requestCounters.content + requestCounters.background;

  // 如果总数為0，随机分配初始请求
  if (total === 0) {
    return Math.random() < 0.4 ? "content" : "background";
  }

  // 计算当前比例
  const contentRatio = requestCounters.content / total;
  const targetContentRatio = 2 / 5; // 0.4

  // 如果 content 的比例低于目标比例，优先分配给 content
  if (contentRatio < targetContentRatio) {
    return "content";
  }

  // 否则分配给 background
  return "background";
}

function getPageHtmlInBackground(url: string) {
  // requestCounters.background++;
  return sendMessage({
    action: "getHtml",
    url,
  })
    .then((res: any) => {
      return res.data;
    })
    .finally(() => {
      // requestCounters.background--;
    });
}

function uploadLogToAliyun(logs: any[]) {
  try {
    sendMessage({
      action: "uploadLogToAliyun",
      data: logs,
    });
  } catch {
    //
  }
}

function getPageHtmlInContent(url: string) {
  // requestCounters.content++;
  return fetch(url, {
    signal: abortController.signal,
  })
    .then((response) => {
      return response.text();
    })
    .catch(() => {
      throw new Error(`采集过于频繁，请清理页面缓存后重新采集`);
    })
    .then((text) => {
      // 获取内容长度（字节），200KB = 200 * 1024 字节
      const minSize = 200 * 1024;
      const maxSize = 10 * 1024 * 1024;
      const sizeInBytes = new TextEncoder().encode(text).length;
      if (sizeInBytes) {
        if (sizeInBytes < minSize) {
          uploadLogToAliyun([
            {
              type: "html-size-too-low",
              html: text,
              url,
            },
          ]);
          // 内容大小小于200KB时主动抛出错误
          throw new Error(`采集过于频繁，请清理页面缓存后重新采集`);
        } else if (sizeInBytes > maxSize) {
          uploadLogToAliyun([
            {
              type: "html-size-too-height",
              html: text,
              url,
            },
          ]);
          // 内容大小大于10MB时主动抛出错误
          throw new Error(`采集过于频繁，请清理页面缓存后重新采集`);
        }
      }

      return text;
    })
    .finally(() => {
      // requestCounters.content--;
    });
}

function getPageHtml(url: string) {
  return new Promise<string>((resolve, reject) => {
    const location = getRequestLocation();
    if (location === "content") {
      getPageHtmlInContent(url)
        .then((data) => {
          resolve(data);
        })
        .catch((error) => {
          reject(error);
        });
    } else {
      getPageHtmlInBackground(url)
        .then((data) => {
          resolve(data);
        })
        .catch(() => {
          reject();
        });
    }
  });
}

interface CrawlResult {
  asinUrlMap?: TAsinUrlMap;
  next?: string;
}

// #region [获取采集链接]
async function crawl(
  url: string,
  claimTemplate: string,
  filterCustomsDeclarationGoods: boolean = false
): Promise<CrawlResult> {
  const result: CrawlResult = {
    asinUrlMap: {},
    next: "",
  };

  let amazonDomain = ""; // 用于存储动态解析的亚马逊站点域名
  const urlParts = new URL(url);
  if (urlParts.hostname.includes("amazon.")) {
    amazonDomain = `https://${urlParts.hostname}`;
  } else {
    console.error("Invalid Amazon URL");
  }
  let htmlText: string | null = null;
  try {
    htmlText = await getPageHtml(url);

    const parser = new DOMParser();
    const doc = parser.parseFromString(htmlText, "text/html");
    const listElement = doc.querySelector(".s-result-list");
    if (listElement) {
      const listItems = listElement.querySelectorAll('[role="listitem"]');
      const asinUrlMap = Array.from(listItems).reduce((object: any, item) => {
        const asin = item.getAttribute("data-asin");
        const itemDetailElement = item.querySelector(
          ".s-product-image-container a"
        ) as HTMLAnchorElement;
        const detailUrl = itemDetailElement?.href || "";

        const deliveryRecipeElement = item.querySelector(
          '[data-cy="delivery-recipe"].a-section'
        );

        let hasDeliveryImage = false;
        if (deliveryRecipeElement) {
          const deliveryImage =
            deliveryRecipeElement.querySelector("img.s-image");
          hasDeliveryImage = !!deliveryImage;
        }

        // 根据filterCustomsDeclarationGoods参数决定是否过滤需要报关的商品
        // 如果filterCustomsDeclarationGoods为true，只添加不需要报关的商品（!hasDeliveryImage）
        // 如果filterCustomsDeclarationGoods为false，添加所有商品
        const shouldAdd = filterCustomsDeclarationGoods
          ? !hasDeliveryImage
          : true;

        if (asin && detailUrl && shouldAdd) {
          object[asin] = { url: detailUrl, claimTemplate };
        }
        return object;
      }, {});

      result.asinUrlMap = asinUrlMap;
    }

    const nextPageUrl =
      doc.querySelector("span.pagnRA a.pagnNext")?.getAttribute("href") ||
      doc.querySelector("#pagnNextLink")?.getAttribute("href") ||
      doc.querySelector(".a-text-center li.a-last a")?.getAttribute("href") ||
      doc
        .querySelector("span.s-pagination-strip li:last-of-type a")
        ?.getAttribute("href") ||
      doc
        .querySelector("span.s-pagination-strip a:last-of-type")
        ?.getAttribute("href") ||
      null;

    const hasDisabledNext = !!doc.querySelector(
      'div[role="navigation"] span.s-pagination-next.s-pagination-disabled'
    );

    result.next =
      nextPageUrl && !hasDisabledNext ? `${amazonDomain}${nextPageUrl}` : "";
  } catch (error: any) {
    alert(`获取当前页采集任务失败: ${error?.message || error}`);
    doCancelCollectChangeButtonHtmlToBackground();
  } finally {
    // 清理 HTML 字符串引用，帮助垃圾回收
    htmlText = null;
  }

  return result;
}
// #endregion

// #region [创建采集任务]
async function getCollectTaskId(
  plusCollectGoodsItems: any[],
  claimTemplate: string
) {
  const storage = await chrome.storage.sync.get(["baoyiplus_accessToken"]);
  const { baoyiplus_accessToken = "" } = storage;
  const res: any = await sendMessage({
    token: baoyiplus_accessToken,
    action: "createCollectTaskApi",
    data: {
      sourceType: "amazon",
      sourceUrl: location.href,
      plusCollectGoodsItems,
      renlingIds: claimTemplate,
    },
  });

  if (res.code === 100001) {
    const errorMessage =
      res.error || res.msg || res.message || "插件版本过低请到ERP重新下载";
    doCancelCollectChangeButtonHtmlToBackground();
    alert(errorMessage);
    throw new Error(errorMessage);
  }
  const sourceSiteCountry = res.data?.sourceSiteCountry || "";
  const asinAndSpuIdMap = (res.data?.plusCollectGoodsItems || []).reduce(
    (obj: Record<string, string>, item: any) => {
      const { id, sourceNo } = item as { id: string; sourceNo: string };
      obj[sourceNo] = id;
      return obj;
    },
    {} as Record<string, string>
  );
  return {
    country: sourceSiteCountry,
    asinAndSpuIdMap,
  };
}
// #endregion

function getProductImages(data: {
  main_image: string;
  main_images: string[];
  skus: any[];
}) {
  const { main_image, main_images, skus } = data;
  const productImages = [main_image, ...main_images];
  skus.forEach((sku) => {
    const { thumb_url, images } = sku;
    if (thumb_url) {
      images.push(thumb_url);
    }
    if (images.length) {
      productImages.push(...images);
    }
  });

  const uniqueProductImages = Array.from(new Set(productImages));
  return uniqueProductImages;
}

function getFormatProductData({
  data,
  ossImageUrlMap,
}: {
  data: any;
  ossImageUrlMap: Record<string, string>;
}) {
  const { main_image, main_images, skus, stock, weight, ...otherProductData } =
    data;
  const oss_main_image = ossImageUrlMap[main_image] || main_image;
  const oss_main_images = main_images.map(
    (image: string) => ossImageUrlMap[image] || image
  );

  const formatSkus = skus.map((sku: any) => {
    const { thumb_url, images, stock, weight } = sku;
    const oss_thumb_url = ossImageUrlMap[thumb_url] || thumb_url;
    const oss_images = images.map(
      (image: string) => ossImageUrlMap[image] || image
    );
    return {
      ...sku,
      oss_image: oss_thumb_url,
      oss_images,
      stock: `${stock}`,
      weight: `${weight}`,
    };
  });

  return {
    main_image,
    main_images,
    oss_image: oss_main_image,
    oss_images: oss_main_images,
    skus: formatSkus,
    stock: `${stock}`,
    weight: `${weight}`,
    ...otherProductData,
  };
}

// #region [上传OSS图片]
const getOssUrl = ({ token, params }: { token: string; params: any }) => {
  return sendMessage({
    action: "getOssUrl",
    data: {
      token,
      params,
    },
  });
};

const getOssInfo = async ({
  images,
}: {
  images: string[];
}): Promise<{ ossUrlMap: Record<string, string> }> => {
  const storage = await chrome.storage.sync.get(["baoyiplus_accessToken"]);
  const { baoyiplus_accessToken } = storage;
  const ossUrlMap: any = {};
  if (baoyiplus_accessToken) {
    const dtos = images.map((item) => {
      const fileType = getFileTypeFromUrl(item);
      const contentType =
        FILE_CONTENT_TYPE[fileType as keyof typeof FILE_CONTENT_TYPE] ||
        "image/jpeg";
      return {
        originUrl: item,
        contentType,
      };
    });
    const res: any = await getOssUrl({
      token: baoyiplus_accessToken,
      params: {
        dtos,
      },
    });

    if (!res || !res.data) {
      return { ossUrlMap: {} };
    }
    (res.data || []).forEach((item: any) => {
      const { originUrl, uploadUrl } = item;
      if (originUrl && uploadUrl) {
        ossUrlMap[originUrl] = uploadUrl;
      }
    });
  }
  return {
    ossUrlMap,
  };
};

const uploadImageToOss = async ({ images }: { images: string[] }) => {
  try {
    const { ossUrlMap } = await getOssInfo({
      images,
    });
    const urlMap: Record<string, string> = {};
    const executor = new ConcurrentExecutor(MAX_DEAL_IMAGE_COUNT); // 最多同时处理5个chunk
    const chunkTasks = images.map((image) => {
      return async () => {
        let file: File | null = null;
        let uploadResponse: Response | null = null;
        try {
          file = await getImageFile(image);
          if (!file) {
            return;
          }
          const uploadUrl = ossUrlMap[image] as any;
          try {
            uploadResponse = await fetch(uploadUrl, {
              method: "PUT",
              body: file,
            });
            if (!uploadResponse.ok) {
              const errorText = await uploadResponse.text();
              console.error(
                `Failed to upload image to OSS: ${uploadUrl}`,
                uploadResponse.status,
                uploadResponse.statusText,
                errorText
              );
              return;
            }
            // 上传成功后，立即释放 file 对象引用
            file = null;
          } catch (err) {
            console.error(
              `Fetch error when uploading image to OSS: ${uploadUrl}`,
              err
            );
            return;
          } finally {
            // 确保清理响应对象
            uploadResponse = null;
          }
          urlMap[image] = removeUrlSearchParams(uploadUrl);
          await sleep(300);
        } catch (e) {
          console.error("error", e);
          // urlMap[image] = image;
        } finally {
          // 确保文件对象被清理，即使上传失败
          file = null;
        }
      };
    });
    await executor.execute(chunkTasks);

    return urlMap;
  } catch {
    return {};
  }
};

// #endregion
function checkFilterDeliverMethod({
  ship_from,
  sold_by,
  filterDeliverMethod,
}: {
  ship_from: string;
  sold_by: string;
  filterDeliverMethod: string[];
}): boolean {
  const lowerShipFrom = ship_from.toLowerCase();
  const lowerSoldBy = sold_by.toLowerCase();
  if (
    filterDeliverMethod.includes("AMZ") &&
    lowerShipFrom.includes("amazon") &&
    lowerSoldBy.includes("amazon")
  ) {
    return true;
  }
  if (
    filterDeliverMethod.includes("FBA") &&
    lowerShipFrom.includes("amazon") &&
    !lowerSoldBy.includes("amazon")
  ) {
    return true;
  }
  if (
    filterDeliverMethod.includes("FBM") &&
    !lowerShipFrom.includes("amazon") &&
    !lowerSoldBy.includes("amazon")
  ) {
    return true;
  }
  return false;
}

// #region [过滤采集条件]
function checkSpuData(data: any, collectConfig: CollectConfig) {
  const {
    price,
    brand,
    title,
    description,
    ship_deliver_time,
    ship_from,
    sold_by,
    number_rating_value,
    __skuCount,
  } = data;

  if (!price) {
    return "采集不到商品价格";
  }
  if (!brand) {
    return "采集不到商品品牌";
  }
  if (!title) {
    return "采集不到商品标题";
  }
  if (!description) {
    return "采集不到商品描述";
  }
  const {
    collectDeliverTime,
    filterDeliverMethod,
    collectMinPrice,
    collectMaxPrice,
    filterScoreLessThan,
    isManualCollect,
    skuNumberLessThan,
  } = collectConfig;
  if (isManualCollect) {
    return "";
  }

  if (Number(skuNumberLessThan) && __skuCount < Number(skuNumberLessThan)) {
    return `采集商品SKU数量不符合采集配置,SKU数量为:${__skuCount}`;
  }

  if (
    Number(collectDeliverTime) &&
    Number(ship_deliver_time) > Number(collectDeliverTime)
  ) {
    return `采集商品到货时间不符合采集配置，到货天数:${ship_deliver_time}`;
  }
  if (ship_from && sold_by) {
    const validFilterDeliverMethod = checkFilterDeliverMethod({
      ship_from,
      sold_by,
      filterDeliverMethod,
    });
    if (!validFilterDeliverMethod) {
      return `采集商品发货模式不符合采集配置，配送方:${ship_from},卖家:${sold_by}`;
    }
  }

  if (
    Number(price) < Number(collectMinPrice) ||
    Number(price) > Number(collectMaxPrice)
  ) {
    return `采集商品价格不符合采集配置,价格:${price}`;
  }
  if (
    Number(filterScoreLessThan) &&
    Number(number_rating_value) < Number(filterScoreLessThan)
  ) {
    return `采集商品评分不符合采集配置,评分:${number_rating_value}`;
  }

  return "";
}

function checkSkuData(data: any, collectConfig: CollectConfig) {
  const { price, title, sku } = data;
  if (!price) {
    return `采集不到商品SKU-${sku}的价格`;
  }
  if (!title) {
    return `采集不到商品SKU-${sku}的标题`;
  }
  return "";
}
// #endregion

// #region [解析采集数据]
function getAsinUrlHtml({
  asin,
  url,
  collectConfig,
}: {
  asin: string;
  url: string;
  collectConfig: CollectConfig;
}): Promise<any> {
  const id = `${asin}_${performance.now()}`;
  return new Promise(async (resolve) => {
    let html: string | null = null;
    try {
      const { maxSkuCount } = collectConfig;
      // const totalStartTime = performance.now();
      // const startTime = performance.now();
      // console.log("开始解析parseSpuData", {
      //   asin,
      //   url,
      // });
      html = await getPageHtml(url);
      const dimensionValuesDisplayData = parseDimensionValuesDisplayData(html);
      // const endHtmlTime = performance.now();
      // console.log(
      //   "解析获取HTML",
      //   ((endHtmlTime - startTime) / 1000).toFixed(2)
      // );
      // const parseSpuDataStartTime = performance.now();
      const parseSpuData = await parseSpuHtml({ html, url, collectConfig });
      // const endTime = performance.now();
      // console.log(
      //   "解析parseSpuData",
      //   ((endTime - parseSpuDataStartTime) / 1000).toFixed(2)
      // );
      const parent_asin = extractParentAsin(html);
      if (!parent_asin) {
        resolve({
          asin,
          url,
          reason: "获取不到父ASIN",
          status: "fail",
          id,
          time: formatTime(),
        });
        return;
      }
      const spuErrorMessage = checkSpuData(
        {
          ...parseSpuData,
          __skuCount: dimensionValuesDisplayData.length || 1,
        },
        collectConfig
      );
      if (spuErrorMessage) {
        // 标记为跳过，而不是失败
        resolve({
          asin,
          url,
          status: "skip",
          reason: spuErrorMessage,
          id,
          time: formatTime(),
        });
        return;
      }

      const { displaySkuInfo, ...baseParseSpuData } = parseSpuData;
      const productData = {
        ...baseParseSpuData,
        asin,
        parent_asin,
        skus: [
          {
            ...displaySkuInfo,
            sku_id: asin,
          },
        ],
      };

      // 把dimensionValuesDisplayData中的asin排除
      const filteredDimensionValues: any[] = dimensionValuesDisplayData.filter(
        (item) => item !== asin
      );
      const inMapSkuAsin = {
        [asin]: true,
      };
      // 创建并发执行器，最多同时执行5个任务

      const filteredDimensionValuesLength = filteredDimensionValues.length;
      while (
        isCollecting &&
        productData.skus.length < maxSkuCount &&
        filteredDimensionValuesLength
      ) {
        const randomDimensionValueIndex = Math.floor(
          Math.random() * filteredDimensionValuesLength
        );
        const childAsin = filteredDimensionValues[randomDimensionValueIndex];
        filteredDimensionValues.splice(randomDimensionValueIndex, 1);
        if (!inMapSkuAsin[childAsin]) {
          inMapSkuAsin[childAsin] = true;
          let childAsinHtml: string | null = null;
          try {
            const childAsinUrl = url.replace(asin, childAsin);
            childAsinHtml = await getPageHtml(childAsinUrl);
            const childSkuData = await parseSkuHtml({
              html: childAsinHtml,
              url,
              collectConfig,
            });
            const checkSkuErrorMessage = checkSkuData(
              {
                ...childSkuData,
                sku: childAsin,
              },
              collectConfig
            );

            const delayTime = Math.floor(Math.random() * 201) + 400; // 400-600 ms
            await sleep(delayTime);

            if (!checkSkuErrorMessage) {
              productData.skus.push({
                sku_id: childAsin,
                ...childSkuData,
              });
            }
          } catch (error) {
            console.error("采集失败", error);
            // 忽略失败的任务
          } finally {
            // 清理 HTML 字符串引用，帮助垃圾回收
            childAsinHtml = null;
          }
        }
      }

      if (!isCollecting) {
        resolve({
          asin,
          url,
          reason: "采集取消",
          status: "fail",
          id,
          time: formatTime(),
        });
        return;
      }

      const collectSkuLength = productData?.skus?.length;

      if (!collectSkuLength) {
        resolve({
          asin,
          url,
          reason: "采集数据有误，商品SKU为空",
          status: "fail",
          id,
          time: formatTime(),
        });
        return;
      }
      const productImages = getProductImages(productData);

      // const startImageTime = performance.now();
      // TODO ZCH 调试
      const ossImageUrlMap = (await uploadImageToOss({
        images: productImages,
      })) as Record<string, string>;
      const formatProductData = getFormatProductData({
        data: productData,
        ossImageUrlMap,
      });
      // -----------------------
      // const formatProductData = getFormatProductData({
      //   data: productData,
      //   ossImageUrlMap: {},
      // });

      // const totalEndTime = performance.now();
      // console.log(
      //   "解析商品SKU时间",
      //   ((totalEndTime - startSkuTime) / 1000).toFixed(2)
      // );
      // console.log(
      //   "解析商品图片时间",
      //   ((totalEndTime - startImageTime) / 1000).toFixed(2)
      // );
      // console.log(
      //   "解析一个商品",
      //   ((totalEndTime - totalStartTime) / 1000).toFixed(2)
      // );

      resolve({
        asin,
        url,
        status: "success",
        data: {
          asin,
          url,
          spuItemParseData: formatProductData,
        },
        id,
        time: formatTime(),
      });
    } catch (error) {
      resolve({
        asin,
        url,
        reason: `采集失败:${error}`,
        status: "fail",
        id,
        time: formatTime(),
      });
    } finally {
      // 清理 HTML 字符串引用，帮助垃圾回收
      html = null;
    }
  });
}
// #endregion

// function extractProductCategories() {
//   const categories = [];
//   // 选择面包屑导航元素
//   const breadcrumbItems = document.querySelectorAll(
//     "#wayfinding-breadcrumbs_feature_div > ul > li"
//   );

//   breadcrumbItems.forEach((item) => {
//     // 查找每个分类项中的链接元素
//     const linkElement = item.querySelector("a");
//     // 存在链接时提取其HTML内容作为分类名称
//     if (linkElement) {
//       categories.push(linkElement.innerHTML);
//     }
//   });
//   console.log(categories)
// }

async function uploadSpuInfo(data: any): Promise<boolean> {
  // // TODO ZCH 调试
  // console.log(data);
  // await sleep(200);
  // return true;

  // const api = "https://110.41.10.45:8001/api/v1/parse-html-crawl-batch-json";
  return new Promise((resolve) => {
    // const api = "http://192.168.168.55:8001/api/v1/parse-html-crawl-batch-json";
    // const api = "http://192.168.168.55:8001/api/v1/parse-html-crawl-batch-json";
    const api =
      "https://callectpost.baoyierp.com/api/v1/parse-html-crawl-batch-json";
    sendMessage({
      action: "uploadSpuInfoInBackground",
      data,
      api,
    }).then((res: any) => {
      if (res?.error) {
        resolve(false);
      } else {
        resolve(true);
      }
    });
  });
}

function collectCurrentPage(
  asinUrlMap: TAsinUrlMap,
  collectConfig: CollectConfig
) {
  sendMessage({
    action: "collectCurrentPage",
    data: {
      asinUrlMap,
      collectConfig,
    },
  });
}
async function doSingleGoodsCollect({
  chunkItemList,
  collectConfig,
}: {
  chunkItemList: any[];
  collectConfig: CollectConfig;
}): Promise<any[]> {
  const collectResultList: any[] = [];
  const chunkPromiseArray: any[] = [];

  const claimTemplate = chunkItemList?.[0]?.[1]?.claimTemplate || "";

  chunkItemList.forEach((item: any) => {
    const [asin, value] = item;
    const { url } = value;
    chunkPromiseArray.push(getAsinUrlHtml({ asin, url, collectConfig }));
  });
  try {
    const chunkItemRes = await Promise.all(chunkPromiseArray);
    let failedCount = 0;
    let skippedCount = 0;
    const { plusCollectGoodsItems, asinAndSpuItemParseDataMap } =
      chunkItemRes.reduce<{
        plusCollectGoodsItems: any[];
        asinAndSpuItemParseDataMap: Record<string, any>;
      }>(
        (obj, result) => {
          const { status, asin, url, data, reason, time } = result;
          const isSkipped = status === "skip";
          collectResultList.push({
            asin,
            status,
            url,
            reason,
            time,
          });
          // 处理成功和失败的结果
          if (status === "success" && asin) {
            const { asin, spuItemParseData, url } = data;
            obj.plusCollectGoodsItems.push({
              goodsUrl: url,
              parentSourceNo: asin,
              sourceNo: asin,
            });
            obj.asinAndSpuItemParseDataMap[asin] = spuItemParseData;
          } else {
            // 区分失败和跳过
            if (isSkipped) {
              // 这是跳过，不是失败
              skippedCount++;
            } else {
              // 这是正常的失败
              failedCount++;
              if (
                result?.reason !==
                "采集失败:Error: 采集过于频繁，请清理页面缓存后重新采集"
              ) {
                uploadLogToAliyun([
                  {
                    type: "collect-fail",
                    ...result,
                  },
                ]);
              }
            }
          }
          return obj;
        },
        {
          plusCollectGoodsItems: [],
          asinAndSpuItemParseDataMap: {},
        }
      );

    const successCount = plusCollectGoodsItems.length;
    if (!successCount) {
      // 即使没有成功，也要统计失败和跳过
      doAddCollectCountFailedToBackground(failedCount);
      doAddCollectCountSkippedToBackground(skippedCount);
      return collectResultList;
    }

    const { country, asinAndSpuIdMap } = await getCollectTaskId(
      plusCollectGoodsItems,
      claimTemplate
    );

    const parsed_data = Object.entries(asinAndSpuItemParseDataMap).map(
      ([asin, spuItemParseData]) => {
        return {
          plat_id: asinAndSpuIdMap[asin],
          ...spuItemParseData,
        };
      }
    );
    const parsedDataLength = parsed_data.length;
    let isUploadSuccess = false;
    if (parsedDataLength) {
      const data = {
        country,
        platform: "amazon", //暂时写死
        version: "1.0.1",
        parsed_data,
      };

      isUploadSuccess = await uploadSpuInfo(data);
    }
    if (isUploadSuccess) {
      doAddCollectCountCurrentToBackground(successCount);
      doAddCollectCountFailedToBackground(failedCount);
      doAddCollectCountSkippedToBackground(skippedCount);
      return collectResultList;
    } else {
      // 上传失败时，需要区分失败和跳过
      // 成功但上传失败的商品算作失败
      doAddCollectCountFailedToBackground(successCount + failedCount);
      doAddCollectCountSkippedToBackground(skippedCount);
      const formatCollectResultList = collectResultList.map((item) => {
        return {
          ...item,
          status: "fail",
          reason: "上传失败",
        };
      });

      return formatCollectResultList;
    }
  } catch (error) {
    const errorCollectResultList = chunkItemList.reduce(
      (list: any, item: any) => {
        const [asin, value] = item;
        const { url } = value;
        list.push({
          asin,
          url,
          status: "fail",
          reason: `采集失败:${error}`,
          time: formatTime(),
        });
        return list;
      },
      []
    );

    return errorCollectResultList;
  } finally {
  }
}

async function doCollectPage({
  pageUrl,
  currentPage,
  maxPages,
  collectConfig,
}: {
  pageUrl: string;
  currentPage: number;
  maxPages: number;
  collectConfig: CollectConfig;
}): Promise<void> {
  if (currentPage > maxPages) {
    return;
  }
  const { claimTemplate, filterCustomsDeclarationGoods } = collectConfig;
  const claimTemplateStr = Array.isArray(claimTemplate)
    ? claimTemplate.join(",")
    : claimTemplate || "";
  const { asinUrlMap, next } = await crawl(
    pageUrl,
    claimTemplateStr,
    filterCustomsDeclarationGoods
  );
  try {
    collectCurrentPage(asinUrlMap || {}, collectConfig);
  } catch (error) {
    alert(`页面采集失败: ${(error as Error).message || error}`);
    doEndCollectChangeButtonHtmlToBackground();
    return;
  }
  if (next) {
    doCollectPage({
      pageUrl: next,
      currentPage: currentPage + 1,
      maxPages,
      collectConfig,
    });
  }
}

async function startCollect() {
  const storage = await chrome.storage.sync.get([
    "baoyiplus_accessToken",
    "baoyiplus_expiresIn",
    "baoyiplus_collectConfig",
  ]);

  const {
    baoyiplus_accessToken,
    baoyiplus_expiresIn,
    baoyiplus_collectConfig,
  } = storage;

  // 从 collectConfig 中获取配置，兼容旧版本存储方式
  let claimTemplate: string = "";
  let maxSkuCount: number = MAX_SPU_COLLECT_SKU_COUNT;
  let filterCustomsDeclarationGoods: boolean = false;

  if (baoyiplus_collectConfig) {
    // 从新配置中读取
    const config = baoyiplus_collectConfig as CollectConfig;
    claimTemplate = Array.isArray(config.claimTemplate)
      ? config.claimTemplate.join(",")
      : config.claimTemplate || "";
    maxSkuCount = config.maxSkuCount || MAX_SPU_COLLECT_SKU_COUNT;
    filterCustomsDeclarationGoods =
      config.filterCustomsDeclarationGoods || false;
  }

  if (!claimTemplate) {
    alert("请先在插件中设置认领模板后再采集发布");
    return;
  }

  const isExpired = checkTokenExpired(baoyiplus_expiresIn);
  if (baoyiplus_accessToken && !isExpired) {
    try {
      const isLogin = await sendMessage({
        token: baoyiplus_accessToken,
        action: "checkIsLogin",
      });
      if (isLogin) {
        const pageUrl = location.href;
        if (pageUrl.includes("/s?")) {
          const inputData = await getInputValues();
          if (!inputData) {
            return;
          }
          startCollectChangeButtonHtml();
          doCollectPage({
            pageUrl,
            currentPage: 1,
            maxPages: Number(inputData?.page) || 1,
            collectConfig: baoyiplus_collectConfig as CollectConfig,
          });
        } else if (pageUrl.includes("/dp/") || pageUrl.includes("/gp/")) {
          const asin = extractAsin(pageUrl);
          if (asin) {
            startCollectChangeButtonHtml();
            collectCurrentPage(
              {
                [asin]: {
                  url: pageUrl,
                  claimTemplate,
                },
              },
              baoyiplus_collectConfig as CollectConfig
            );
          } else {
            alert("获取不到该商品ASIN");
          }
        }
      } else {
        alert("登录失效,请点击右上角插件重新登录");
      }
    } catch (error) {
      alert("登录失效,请点击右上角插件重新登录");
    }
  } else {
    alert("还未登录，请先点击右上角插件进行登录");
  }
}

async function startCollectKeyword({
  pageUrl,
  collectConfig,
  claimTemplate,
  maxPages,
}: {
  pageUrl: string;
  collectConfig: CollectConfig;
  claimTemplate: string;
  maxPages: number;
}) {
  if (pageUrl.includes("/s?")) {
    startCollectChangeButtonHtml();
    await doCollectPage({
      pageUrl,
      currentPage: 1,
      maxPages: maxPages || 1,
      collectConfig,
    });
  } else if (pageUrl.includes("/dp/") || pageUrl.includes("/gp/")) {
    const asin = extractAsin(pageUrl);
    if (asin) {
      startCollectChangeButtonHtml();
      collectCurrentPage(
        {
          [asin]: {
            url: pageUrl,
            claimTemplate,
          },
        },
        collectConfig
      );
    } else {
      alert("获取不到该商品ASIN");
    }
  }
}

async function startCollectMultiKeyword({
  collectConfig,
  multiKeywordCollectData,
}: {
  collectConfig: CollectConfig;
  multiKeywordCollectData: TMultiKeywordCollectData;
}) {
  const storage = await chrome.storage.sync.get([
    "baoyiplus_accessToken",
    "baoyiplus_expiresIn",
  ]);

  const { baoyiplus_accessToken, baoyiplus_expiresIn } = storage;

  // 从 collectConfig 中获取配置，兼容旧版本存储方式
  let claimTemplate: string = "";
  let maxSkuCount: number = MAX_SPU_COLLECT_SKU_COUNT;
  let filterCustomsDeclarationGoods: boolean = false;

  // 从新配置中读取
  claimTemplate = Array.isArray(collectConfig.claimTemplate)
    ? collectConfig.claimTemplate.join(",")
    : collectConfig.claimTemplate || "";
  maxSkuCount = collectConfig.maxSkuCount || MAX_SPU_COLLECT_SKU_COUNT;
  filterCustomsDeclarationGoods =
    collectConfig.filterCustomsDeclarationGoods || false;

  if (!claimTemplate) {
    alert("请先在插件中设置认领模板后再采集发布");
    return;
  }

  const isExpired = checkTokenExpired(baoyiplus_expiresIn);
  if (baoyiplus_accessToken && !isExpired) {
    try {
      const isLogin = await sendMessage({
        token: baoyiplus_accessToken,
        action: "checkIsLogin",
      });
      if (isLogin) {
        const { multiKeywordPage, multiKeywordCollectionList } =
          multiKeywordCollectData;
        const originUrl = location.origin;
        for (let i = 0; i < multiKeywordCollectionList.length; i++) {
          const keyword = multiKeywordCollectionList[i];
          const pageUrl = `${originUrl}/s?k=${keyword}`;
          await startCollectKeyword({
            pageUrl,
            collectConfig,
            claimTemplate,
            maxPages: Number(multiKeywordPage),
          });
        }
      } else {
        alert("登录失效,请点击右上角插件重新登录");
      }
    } catch (error) {
      alert("登录失效,请点击右上角插件重新登录");
    }
  } else {
    alert("还未登录，请先点击右上角插件进行登录");
  }
}

chrome.runtime.onConnect.addListener((port) => {
  if (port.name === "background-to-content-collect-goods") {
    // 接收 background 发送的数据
    port.onMessage.addListener(async (message) => {
      if (message.type === "DO_COLLECT_GOODS") {
        try {
          // 1. 执行 content 自己的异步函数（例如处理数据、DOM 操作等）
          const collectResultList = await doSingleGoodsCollect(message.data);

          // 2. 向 background 发送"处理完成"的通知
          try {
            port.postMessage({
              type: "COLLECT_GOODS_CONTENT_DONE",
              result: collectResultList,
            });

            // 检查 postMessage 是否成功
            if (chrome.runtime.lastError) {
              console.error("发送消息失败:", chrome.runtime.lastError.message);
            }
          } catch (error) {
            console.error("发送消息异常:", error);
          }

          // 3. 延迟断开连接，确保消息已发送
          // 注意：不要立即断开，让 background 端先收到消息
          setTimeout(() => {
            try {
              port.disconnect();
            } catch (e) {
              // 连接可能已经断开，忽略错误
            }
          }, 100);
        } catch (error) {
          // 处理出错时通知 background
          try {
            port.postMessage({
              type: "COLLECT_GOODS_CONTENT_ERROR",
              error,
            });

            // 检查 postMessage 是否成功
            if (chrome.runtime.lastError) {
              console.error(
                "发送错误消息失败:",
                chrome.runtime.lastError.message
              );
            }
          } catch (e) {
            console.error("发送错误消息异常:", e);
          }

          // 延迟断开连接，确保消息已发送
          setTimeout(() => {
            try {
              port.disconnect();
            } catch (e) {
              // 连接可能已经断开，忽略错误
            }
          }, 100);
        }
      }
    });

    // 监听连接断开
    port.onDisconnect.addListener(() => {
      console.log("与 background 的连接已断开");
    });
  }
});

// 监听 background 发送的消息（与 V2 完全一致）
chrome.runtime.onMessage.addListener((message, sender, sendResponse) => {
  // 处理消息并回复
  if (message.action === "endCollectChangeButtonHtml") {
    const { collectCountMap } = message.data;
    endCollectChangeButtonHtml(collectCountMap);
  } else if (message.action === "cancelCollectChangeButtonHtml") {
    cancelCollectChangeButtonHtml();
  } else if (message.action === "startMultiKeywordCollect") {
    const { collectConfig, multiKeywordCollectData } = message.data;
    // 立即发送响应，因为采集任务是长时间运行的后台任务
    sendResponse({ success: true });
    // 异步执行采集任务，不阻塞消息响应
    startCollectMultiKeyword({ collectConfig, multiKeywordCollectData }).catch(
      (error) => {
        console.error("多关键词采集执行失败:", error);
      }
    );
    return true; // 保持消息通道开放（虽然已经发送了响应，但这是最佳实践）
  } else if (message.action === "changeCollectCount") {
    const { collectCountMap } = message.data;
    if (Number(collectCountMap.total)) {
      changeCollectCount(collectCountMap);
    }
  } else if (message.action === "startCollectChangeButtonHtml") {
    startCollectChangeButtonHtml();
  }
});

// 监听页面关闭/刷新事件
const handleBeforeUnload = () => {
  sendMessage({
    action: "collectPageUnload",
  });
};

// 绑定事件监听
window.addEventListener("beforeunload", handleBeforeUnload);

// 可选：页面正常卸载时移除监听（优化内存）
window.addEventListener("unload", () => {
  window.removeEventListener("beforeunload", handleBeforeUnload);
});
